﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.Globalization;

namespace PSE.Communication.Fix.Common
{
    public class FixConverterExecutionReport : IFixModelConverter<ExecutionReportEntity>
    {
        FixConfigurationSection fixConfiguration = (FixConfigurationSection)ConfigurationManager.GetSection("fixConfiguration");

        public FixConverterExecutionReport()
        {
            fixConfiguration = (FixConfigurationSection)ConfigurationManager.GetSection("fixConfiguration");

            if (fixConfiguration == null)
                throw new Exception("Section fixConfiguration not found in the config file");
        }

        public List<ExecutionReportEntity> ConvertTo(List<RepositoryMessage> messages)
        {
            List<ExecutionReportEntity> executionReportEntities = new List<ExecutionReportEntity>();

            foreach (RepositoryMessage item in messages)
            {
                executionReportEntities.Add(ConvertTo(item));
            }

            return executionReportEntities;

        }

        public ExecutionReportEntity ConvertTo(RepositoryMessage message)
        {
            ExecutionReportEntity model = new ExecutionReportEntity();

            Dictionary<int, string> dic = new Dictionary<int, string>();

            string[] fields = message.Message.Split('');

            NumberFormatInfo numberFormatInfo = new CultureInfo("en-US").NumberFormat;

            for (int i = 0; i < fields.Length - 1; i++)
            {
                int type = Convert.ToInt32(fields[i].Split('=')[0]);
                string value = fields[i].Split('=')[1];
                if (type == 382)
                {
                    dic.Add(type, value);
                    i++;
                    string value375 = string.Empty;
                    for (int j = 0; j < Convert.ToInt32(value); j++)
                    {
                        int type382 = Convert.ToInt32(fields[i].Split('=')[0]);
                        string value382 = fields[i].Split('=')[1];
                        if (type382 == 375)
                        {
                            value375 += fields[i].Split('=')[1] + '';
                            i++;
                        }
                    }
                    dic.Add(375, value375);
                }
                if (type == 453)
                {
                    dic.Add(type, value);
                    i++;
                    string value448 = string.Empty;
                    string value447 = string.Empty;
                    string value452 = string.Empty;
                    for (int j = 0; j < Convert.ToInt32(value) * 3; j++)
                    {
                        int type453 = Convert.ToInt32(fields[i].Split('=')[0]);
                        string value453 = fields[i].Split('=')[1];
                        switch (type453)
                        {
                            case 448:
                                {
                                    value448 += fields[i].Split('=')[1] + '';
                                    i++;
                                    break;
                                }
                            case 447:
                                {
                                    value447 += fields[i].Split('=')[1] + '';
                                    i++;
                                    break;
                                }
                            case 452:
                                {
                                    value452 += fields[i].Split('=')[1] + '';//Alter to EntryPoint
                                    i++;
                                    break;
                                }
                            default:
                                break;
                        }
                    }
                    dic.Add(448, value448);
                    dic.Add(447, value447);
                    dic.Add(452, value452);//Alter to EntryPoint
                    i--;
                }
                else if ((type != 453) && (type != 382))
                {
                    dic.Add(type, value);
                }
            }



            if (dic.ContainsKey(34))
                model.MsgSeqNum = Convert.ToInt32(dic[34]);
            if (dic.ContainsKey(11))
                model.ClOrdID = dic[11];
            if (dic.ContainsKey(40)) //Alter to EntryPoint
                model.OrdType = Convert.ToChar(dic[40]);
            if (dic.ContainsKey(54))
                model.Side = Convert.ToChar(dic[54]);
            if (dic.ContainsKey(38))
                model.OrderQty = Convert.ToDouble(dic[38], numberFormatInfo);

            if (dic.ContainsKey(453))
                if (!String.IsNullOrEmpty(dic[453]))  //NoPartyIDs
                {
                    int partiesCount = Convert.ToInt32(dic[453]);

                    List<NoPartyIDEntity> partiesModel = new List<NoPartyIDEntity>(partiesCount);
                    string[] field448 = dic[448].Split('');
                    string[] field447 = dic[447].Split('');
                    string[] field452 = dic[452].Split('');//Alter to EntryPoint
                    for (int j = 0; j < partiesCount; j++)
                    {
                        NoPartyIDEntity partyIDEntity = new NoPartyIDEntity();
                        partyIDEntity.PartyID = field448[j];
                        partyIDEntity.PartyIDSource = Convert.ToChar(field447[j]);
                        partyIDEntity.PartyRole = Convert.ToInt32(field452[j]);//Alter to EntryPoint
                        partiesModel.Add(partyIDEntity);
                    }
                    model.NoParties = partiesModel;
                }

            if (dic.ContainsKey(52))
                model.SendingTime = dic[52];
            if (dic.ContainsKey(37))
                model.OrderID = dic[37];
            if (dic.ContainsKey(41))
                model.ClOrdID = dic[41];
            if (dic.ContainsKey(198))
                model.SecondaryOrderID = dic[198];
            if (dic.ContainsKey(548))
                model.CrossID = dic[548];
            if (dic.ContainsKey(17))
                model.ExecID = dic[17];
            if (dic.ContainsKey(19))
                model.ExecRefID = dic[19];
            if (dic.ContainsKey(55))
                model.Symbol = dic[55];
            if (dic.ContainsKey(48))
                model.SecurityID = dic[48];
            if (dic.ContainsKey(22))
                model.SecurityIDSource = dic[22];
            if (dic.ContainsKey(207))
                model.SecurityExchange = dic[207];
            if (dic.ContainsKey(150))
                model.ExecType = Convert.ToChar(dic[150]);//Alter to EntryPoint
            if (dic.ContainsKey(39)) //Alter to EntryPoint
                model.OrdStatus = Convert.ToChar(dic[39]);
            if (dic.ContainsKey(10029))
                model.BTSFinalTxOrdStatus = Convert.ToChar(dic[10029]);
            if (dic.ContainsKey(378))
                model.ExecRestatementReason = Convert.ToInt32(dic[378]);
            if (dic.ContainsKey(636))
                model.WorkingIndicator = Convert.ToChar(dic[636]);
            if (dic.ContainsKey(103)) //Alter to EntryPoint
                model.OrdRejReason = Convert.ToInt32(dic[103]);
            if (dic.ContainsKey(44))
                model.Price = Convert.ToDouble(dic[44], numberFormatInfo);
            if (dic.ContainsKey(99))
                model.StopPx = Convert.ToDouble(dic[99], numberFormatInfo);
            if (dic.ContainsKey(6))
                model.AvgPx = Convert.ToDouble(dic[6], numberFormatInfo);
            if (dic.ContainsKey(32))
                model.LastQty = Convert.ToDouble(dic[32], numberFormatInfo);
            if (dic.ContainsKey(31))
                model.LastPx = Convert.ToDouble(dic[31], numberFormatInfo);
            if (dic.ContainsKey(110))
                model.MinQty = Convert.ToDouble(dic[110], numberFormatInfo);
            if (dic.ContainsKey(111))
                model.MaxFloor = Convert.ToDouble(dic[111], numberFormatInfo);
            if (dic.ContainsKey(151))//Alter to EntryPoint
                model.LeavesQty = Convert.ToDouble(dic[151], numberFormatInfo);
            if (dic.ContainsKey(14))
                model.CumQty = Convert.ToDouble(dic[14], numberFormatInfo);//Alter to EntryPoint
            if (dic.ContainsKey(9757))
                model.OrigOrdQty = Convert.ToDouble(dic[9757], numberFormatInfo);
            if (dic.ContainsKey(59))
                model.TimeInForce = Convert.ToChar(dic[59]);//Alter to EntryPoint

            if (dic.ContainsKey(75))
            {
                DateTime d = DateTime.MinValue;
                DateTime.TryParseExact(dic[75].ToString(), "yyyyMMdd", null, System.Globalization.DateTimeStyles.None, out d);
                model.TradeDate = d;
            }

            if (dic.ContainsKey(6032))
                model.UniqueTradeID = dic[6032];
            if (dic.ContainsKey(1))
                model.AccountNumber = dic[1];
            if (dic.ContainsKey(337))
                model.ContraTrader = dic[337];
            if (dic.ContainsKey(60))
                model.TransactTime = dic[60];
            if (dic.ContainsKey(58))
                model.Text = dic[58];
            if (dic.ContainsKey(826))
                model.TradeAllocIndicator = Convert.ToInt32(dic[826]);
           
            #region [ ENTRYPOINT - New Fields ]
            if (dic.ContainsKey(581))
                model.AccountType = Convert.ToInt32(dic[581]);

            if (dic.ContainsKey(1057))
            {
                string value = Convert.ToString(dic[1057]);
                bool result = false;
                if(value.Equals("Y", StringComparison.InvariantCultureIgnoreCase))
                    result = true;

                model.AggressorIndicator = result;
            }

            if (dic.ContainsKey(5149))
                model.Memo = Convert.ToString(dic[5149]);

            if (dic.ContainsKey(35001))
                model.ProtectionPrice = Convert.ToDouble(dic[35001], numberFormatInfo);

            if (dic.ContainsKey(432))
            {
                model.ExpireData = null;
                DateTime d = DateTime.MinValue;
                bool converted = DateTime.TryParseExact(dic[432].ToString(), "yyyyMMdd", null, System.Globalization.DateTimeStyles.None, out d);
                if(converted)
                    model.ExpireData = d;
            }
            #endregion [ ENTRYPOINT - New Fields ]

            model.CodMessage = message.CodMessage;

            return model;
        }
    }
}